package com.zenchn.utils;


import org.lionsoul.ip2region.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * Ip2Region 插件自定义实现
 *  binary 和 b-tree算法（线程不安全）可能会打开文件数过多的错误，请修改内核的最大允许打开文件数(fs.file-max=一个更高的值)
 *  memory算法（线程安全） 整个数据库全部载入内存
 * @author dingxinfa
 * @date 2020-03-31
 */
public class Ip2RegionUtils {
    private static final Logger log = LoggerFactory.getLogger(Ip2RegionUtils.class);



    /**
     * 根据IP获取 清洁地址 默认算法 memory
     * 国家|大区|省份|城市|运营商  [未知写0,清洗掉0,及内网IP重复文案]
     * @param ip
     * @return 国家|大区|省份|城市|运营商  [未知写0,清洗掉0,及内网IP重复文案]
     */
    public  static String getCleanAddress(String ip){
        return getCleanAddress(ip, DbSearcher.MEMORY_ALGORITYM);
    }


    /**
     * 根据IP获取 清洁地址
     * 国家|大区|省份|城市|运营商  [未知写0,清洗掉0,及内网IP重复文案]
     * @param ip
     * @param algorithm 查询算法
     * @return 国家|大区|省份|城市|运营商  [未知写0,清洗掉0,及内网IP重复文案]
     * @see DbSearcher
     * DbSearcher.BTREE_ALGORITHM; //B-tree
     * DbSearcher.BINARY_ALGORITHM //Binary
     * DbSearcher.MEMORY_ALGORITYM //Memory
     */
    public  static String getCleanAddress(String ip, int algorithm){
        String address=getAddress(ip,algorithm);
        if (address.contains("内网IP") || address.contains("内网ip")){
            return "内网IP";
        }
        return Arrays.stream(address.split("\\|")).filter(r-> !"0".equals(r)).collect(Collectors.joining("|"));
    }


    /**
     * 根据IP获取地址 默认算法 memory
     *
     * @return 国家|区域|省份|城市|ISP
     */
    public static String getAddress(String ip) {
        return getAddress(ip, DbSearcher.MEMORY_ALGORITYM);
    }

    /**
     * 根据IP获取地址
     *
     * @param ip
     * @param algorithm 查询算法
     * @return 国家|区域|省份|城市|ISP
     * @see DbSearcher
     * DbSearcher.BTREE_ALGORITHM; //B-tree
     * DbSearcher.BINARY_ALGORITHM //Binary
     * DbSearcher.MEMORY_ALGORITYM //Memory
     */

    public static String getAddress(String ip, int algorithm) {
        if (!Util.isIpAddress(ip)) {
            log.error("根据IP获取地址-错误格式的ip地址: {}", ip);
            return "";
        }

        try {
            //获取ip库的位置（放在src下）（直接通过测试类获取文件Ip2RegionTest为测试类）

            //String dbFile = Ip2RegionUtils.class.getResource("/ip2region.db").getPath();
            //return new DbSearcher(new DbConfig(), URLDecoder.decode(dbFile, "utf-8"));

            //正式发布后 db文件放在jar内，不可通过file 读取，只能通过 InputStream
            InputStream inputStream = Ip2RegionUtils.class.getResourceAsStream("/ip2region.db");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            byte[] dbByte = baos.toByteArray();
            inputStream.close();
            baos.close();

            DbSearcher searcher = new DbSearcher(new DbConfig(), dbByte);
            DataBlock dataBlock;
            switch (algorithm) {
                case DbSearcher.BTREE_ALGORITHM:
                    dataBlock = searcher.btreeSearch(ip);
                    break;
                case DbSearcher.BINARY_ALGORITHM:
                    dataBlock = searcher.binarySearch(ip);
                    break;
                case DbSearcher.MEMORY_ALGORITYM:
                    dataBlock = searcher.memorySearch(ip);
                    break;
                default:
                    log.error("根据IP获取地址-未传入正确的查询算法");
                    return "";
            }
            return dataBlock.getRegion();

        } catch (DbMakerConfigException | IOException e) {
            e.printStackTrace();
            log.error("根据IP获取地址-错误异常: {}", e.getMessage());
        }
        return "";
    }



    public static void main(String[] args) {

        //打印位置信息（格式：国家|大区|省份|城市|运营商）
        System.out.println(Ip2RegionUtils.getCleanAddress("69.171.225.13"));
        System.out.println(Ip2RegionUtils.getCleanAddress("61.132.163.68"));
        System.out.println(Ip2RegionUtils.getCleanAddress("219.141.136.10"));
        System.out.println(Ip2RegionUtils.getCleanAddress("61.128.128.68"));
        System.out.println(Ip2RegionUtils.getCleanAddress("218.85.152.99"));

        System.out.println(Ip2RegionUtils.getCleanAddress("202.103.225.68"));
        System.out.println(Ip2RegionUtils.getCleanAddress("61.153.177.196"));
        System.out.println(Ip2RegionUtils.getCleanAddress("202.106.195.68"));
        System.out.println(Ip2RegionUtils.getCleanAddress("202.99.160.68"));
        System.out.println(Ip2RegionUtils.getCleanAddress("202.99.104.68"));
        System.out.println(Ip2RegionUtils.getCleanAddress("221.11.1.67"));

        System.out.println(Ip2RegionUtils.getCleanAddress("127.0.0.1"));
        System.out.println(Ip2RegionUtils.getCleanAddress("192.168.1.121"));
        System.out.println(Ip2RegionUtils.getCleanAddress("10.1.5.24"));


    }

}
